﻿using Consul;
using Furion.ConfigurableOptions;
using Furion.DataEncryption.Extensions;
using Microsoft.AspNetCore.Builder;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting;
using Microsoft.Extensions.Options;
using StackExchange.Profiling.Internal;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace Furion.CMS.Core.Extensions
{
    /// <summary>
    /// Consul Service Options
    /// </summary>
    public class ConsulServiceOptions : IConfigurableOptions
    {
        /// <summary>
        /// 服务注册地址（Consul的地址）
        /// </summary>
        public string ConsulAddress { get; set; }

        /// <summary>
        /// 服务ID
        /// </summary>
        public string ServiceId { get; set; }

        /// <summary>
        /// 服务名称
        /// </summary>
        public string ServiceName { get; set; }

        /// <summary>
        /// 健康检查地址
        /// </summary>
        public string HealthCheck { get; set; }
    }

    public static class ConsulRegistrationExtensions
    {
        /// <summary>
        /// 添加Consul
        /// </summary>
        /// <param name="service"></param>
        public static void AddConsul(this IServiceCollection service)
        {
            // 读取服务配置文件
            var config = new ConfigurationBuilder().AddJsonFile("consulconfig.json").Build();
            service.Configure<ConsulServiceOptions>(config);
        }

        /// <summary>
        /// 使用Consul
        /// </summary>
        /// <param name="app"></param>
        /// <returns></returns>
        public static IApplicationBuilder UseConsul(this IApplicationBuilder app)
        {
            // 获取主机生命周期管理接口
            var lifetime = app.ApplicationServices.GetRequiredService<IHostApplicationLifetime>();

            // 获取服务配置项
            var configuration = app.ApplicationServices.GetRequiredService<IConfiguration>();
            var url = configuration["urls"].ToSplit(";").FirstOrDefault();
            var serviceOptions = app.ApplicationServices.GetRequiredService<IOptions<ConsulServiceOptions>>()?.Value;
            if (serviceOptions != null && !url.IsNullOrWhiteSpace())
            {
                // 获取当前服务地址和端口，配置方式
                var uri = new Uri(url);

                // 服务ID必须保证唯一,采用地址+端口进行MD5加密来生成服务id确保唯一性
                serviceOptions.ServiceId = url.ToMD5Encrypt();

                var consulClient = new ConsulClient(configuration =>
                {
                    //服务注册的地址，集群中任意一个地址
                    configuration.Address = new Uri(serviceOptions.ConsulAddress);
                });

                // 节点服务注册对象
                var registration = new AgentServiceRegistration()
                {
                    ID = serviceOptions.ServiceId,
                    Name = serviceOptions.ServiceName,// 服务名
                    Address = uri.Host,
                    Port = uri.Port, // 服务端口
                    Check = new AgentServiceCheck
                    {
                        // 注册超时
                        Timeout = TimeSpan.FromSeconds(5),
                        // 服务停止多久后注销服务
                        DeregisterCriticalServiceAfter = TimeSpan.FromSeconds(5),
                        // 健康检查地址
                        HTTP = $"{uri.Scheme}://{uri.Host}:{uri.Port}{serviceOptions.HealthCheck}",
                        // 健康检查时间间隔
                        Interval = TimeSpan.FromSeconds(10),
                    }
                };

                // 注册服务
                consulClient.Agent.ServiceRegister(registration).Wait();

                // 应用程序终止时，注销服务
                lifetime.ApplicationStopping.Register(() =>
                {
                    consulClient.Agent.ServiceDeregister(serviceOptions.ServiceId).Wait();
                });
            }

            return app;
        }
    }
}
